#include "ConfModule.h"

QScopedPointer<ConfModule> ConfModule::ms_instance;
ConfModule::ConfModule(QObject *parent)
    :BaseModule(s_moduleName,parent)
    ,m_fileSystemWatcher(new QFileSystemWatcher(this))
    ,m_defaultFilePath(gs_defaultConfFilePath)
    ,m_cacheFolderPath(gs_cacheFolderPath)
    ,m_confFileName(gs_confFileName)
{
    checkDir(m_cacheFolderPath);
    m_fileSystemWatcher->addPath(m_cacheFolderPath);
    m_fileSystemWatcher->addPath(m_cacheFolderPath+m_confFileName);
    m_fileSystemWatcher->addPath(m_defaultFilePath);
    connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,this, &ConfModule::checkDir);
    connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, &ConfModule::readConf);
}

ConfModule::~ConfModule()
{

}

ConfModule* ConfModule::instance(void)
{
    if (ms_instance.isNull()) {
        ms_instance.reset(new ConfModule());
    }
    return ms_instance.data();
}

QJsonObject ConfModule::readJson(const QString &filePath)
{

    QFile file(filePath);
    QJsonDocument jsonDoc;
    QJsonObject jsonObj;
    if(file.exists())
    {
        if(file.open(QFile::OpenModeFlag::ReadOnly))
        {
            jsonDoc = QJsonDocument::fromJson(file.readAll());
            if(jsonDoc.isObject())
            {
                jsonObj = jsonDoc.object();
            }
            else
            {
                qWarning()<<filePath<<" don't json object";
            }
            file.close();
        }
        else
        {
            qWarning()<<filePath<<" don't opened";
        }
    }
    else{
        qWarning()<<filePath<<" don't exist";
    }
    return jsonObj;
}

void ConfModule::writeJson(const QString &filePath, QJsonObject &jsonObj)
{
    QFile file(filePath);
    int32_t writeByteNum;
    if(!file.open(QIODevice::ReadWrite|QIODevice::Truncate))
    {
        qWarning() << "DeviceConf:openFailed " << file.errorString();
        return;
    }
    writeByteNum = file.write(QJsonDocument(jsonObj).toJson(QJsonDocument::Indented));
    if(writeByteNum <= 0)
    {
        qWarning() << "DeviceConf:writeByteNum="<<writeByteNum;
    }
    file.close();
}

void ConfModule::readConf(const QString &filePath)
{
    QJsonObject defaultConfJsonObj = readJson(m_defaultFilePath);
    QJsonObject confJsonObj = readJson(filePath);
    QJsonObject sendConfJsonObj;
    for(auto iter = defaultConfJsonObj.begin();iter != defaultConfJsonObj.end();iter++)
    {
        if(iter.value().isObject())
        {
            QString moduleName = iter.key();
            if(!confJsonObj.isEmpty()
                && confJsonObj.contains(moduleName)
                && confJsonObj[moduleName].isObject())
            {
                sendConfJsonObj.insert(moduleName,confJsonObj[moduleName].toObject());
            }
        }
    }
    if(!sendConfJsonObj.isEmpty() && !defaultConfJsonObj.isEmpty())
    {
        qDebug()<<"ConfModule::readConf: file="<<m_fileSystemWatcher->files();
        emit sendConf(sendConfJsonObj,defaultConfJsonObj);
    }
    if(!m_fileSystemWatcher->files().contains(filePath))
    {
        m_fileSystemWatcher->addPath(filePath);
    }
}

void ConfModule::updateProperty(const QJsonObject &conf, const QJsonObject &defaultConf)
{

}

void ConfModule::writeConf(const QString &moduleName, const QString &key, const QVariant &value)
{
    QJsonObject confJsonObj = readJson(m_cacheFolderPath+m_confFileName);
    QJsonObject moduleJsonObj;
    if(confJsonObj.contains(moduleName)&&confJsonObj[moduleName].isObject())
    {
        moduleJsonObj = confJsonObj[moduleName].toObject();
        moduleJsonObj[key] = value.toJsonValue();
        confJsonObj[moduleName] = moduleJsonObj;
    }
    else
    {
        moduleJsonObj[key] = value.toJsonValue();
        confJsonObj.insert(moduleName,moduleJsonObj);
    }
    writeJson(m_cacheFolderPath+m_confFileName,confJsonObj);
    if(!m_fileSystemWatcher->files().contains(m_cacheFolderPath+m_confFileName))
    {
        m_fileSystemWatcher->addPath(m_cacheFolderPath+m_confFileName);
    }
}

void ConfModule::checkDir(const QString &folderPath)
{
    QDir tempDir(folderPath);
    if(!tempDir.exists())
    {
        tempDir.mkpath(folderPath);
    }
}
